#include "freertos/FreeRTOS.h"
#include "freertos/task.h"


#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"

#include "model.h"
#include "mfcc.h"
#include "closewav.h"

typedef struct 
{
  char*name;
  const uint16_t*data;
}UserLabel;

float*tensorInput;



//执行器运行的状态
int tensorFlowRunState=0;


int getMaxIndex(int8*data,int len){
  int index=0;
  int8 temp=0;
  for(int i=0;i<len;i++){
    if(data[i]>temp){
      temp=data[i];
      index=i;
    }
  }
  return index;
}

#define KZ 6
#define KISSSIZE 256


float*inputRecord;

int countIndex=0;
#define blockSize 256
uint16_t * data=NULL;
int ringIndex=0;
//int16_t record[512];
int16_t*record;
int16_t lastData=0;



namespace {
    tflite::ErrorReporter* error_reporter = nullptr;
    const tflite::Model* model = nullptr;
    tflite::MicroInterpreter* interpreter = nullptr;
    TfLiteTensor* input = nullptr;
    TfLiteTensor* output = nullptr;
    int inference_count = 0;
    
    constexpr int kTensorArenaSize = 20000;
    //uint8_t tensor_arena[kTensorArenaSize];
    uint8_t*tensor_arena;
    
}  // namespace




int getAvg(int16_t *data,int size){
    int total=0;
    for(int i=0;i<size;i++){
        if(data[i]<0){
        total+= (-data[i]);
        }else{
        total+=data[i];
        }
    }
    return total/size;
}


#define Limitr 40
char ls[12]={0};



void loop(){
    float*out=tensorInput;
    unsigned short *testData=(unsigned short *)closewav;
    lastData=0;
    for(int i=0;i<62;i++){
        //获取数组数据
        for(int j=0;j<512;j++){
        int temp=i*256+j;
        if(temp>16000){
            record[j]=0;
        }else{
            record[j]=testData[temp];
        }
        }
        //便利record里面的数据做预加重
        for(int j=0;j<512;j++){
        if(j>0){
            inputRecord[j]=record[j]*1.0 - 0.97 *record[j-1];
        }else{
            inputRecord[j]=record[j]*1.0 - 0.97 *lastData;
        }
        lastData=record[j];
        }

        mfcc(inputRecord,out+i*13);

    }
    TfLiteStatus invoke_status = interpreter->Invoke();
    
    if (invoke_status != kTfLiteOk) {
        printf("Invoke failed on x: %f\r\n",2.0);
        return;
    }
    int maxIndex=getMaxIndex(output->data.int8,output->dims->data[1]);
    printf("result:");

    for(int i=0;i<output->dims->data[1];i++){
        int8_t t=output->data.int8[i];
        printf(" %d ",t);
    }
    printf("\r\n");
    printf("name:%s,index:%d  \r\n\r\n",cmdName[maxIndex],maxIndex);

    printf("end .......\r\n");

    vTaskDelay(5000 / portTICK_PERIOD_MS); 

}

void loop_task(void *pvParameters){
    while(1){
        loop();
    }
    vTaskDelete(NULL);
}


extern "C" void app_main() {

    printf("hello init......\r\n");
    
    record=(int16_t*)malloc(512*sizeof(int16_t));


    static tflite::MicroErrorReporter micro_error_reporter;
    error_reporter = &micro_error_reporter;
  
    //加载模型
    model = tflite::GetModel(model_tflite);
    printf("model version:%ld\r\n",model->version());
    if (model->version() != TFLITE_SCHEMA_VERSION) {
      TF_LITE_REPORT_ERROR(error_reporter,
                           "Model provided is schema version %d not equal "
                           "to supported version %d.",
                           model->version(), TFLITE_SCHEMA_VERSION);
      return;
    }
  
    tensor_arena=(uint8_t*)malloc(kTensorArenaSize);
    if(tensor_arena==NULL){
      printf("mem free error!\r\n");
      return;
    }
  
    static tflite::AllOpsResolver resolver;
    //初始化
    static tflite::MicroInterpreter static_interpreter(
        model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
    //赋值给全局变量
    interpreter = &static_interpreter;
  
    //内存分配
    // Allocate memory from the tensor_arena for the model's tensors.
    TfLiteStatus allocate_status = interpreter->AllocateTensors();
    if (allocate_status != kTfLiteOk) {
      TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
      return;
    }
    //获取输入输出张量指针
    input = interpreter->input(0);
    tensorInput=input->data.f;
    output = interpreter->output(0);
    //startAudio();
    fft_init();
    init_mel_filters();
    inputRecord=(float*)malloc(512*sizeof(float));
    printf("--------------init-----------------\r\n");
    xTaskCreate(loop_task, "Task 1", 1024*5, NULL, 1,NULL);

}